/************************************
 * created by Tonk (tonk@ctonk.com) *
 ************************************/

// vEditHandler.cpp

#ifndef VEDIT_HANDLER_CPP
#define VEDIT_HANDLER_CPP

#include "definitions.h"
#include "split.h"
#include "vEditHandler.h"
#include "stringutil.h"
#include "commandTable.h"
#include "character.h"

vEditHandler::vEditHandler() {
	_c = 0;
	_dest = 0;
	_nLines = 0;
}

vEditHandler::vEditHandler( Character* c, std::string* dest ) {
	int i = 0;
	char ch = '\0';
	_c = c;
	_dest = dest;
	for ( std::string::iterator it = _dest->begin(); it != _dest->end(); it++ ) {
		ch = *it;
		if ( ch  == '\n' ) {
			i++;
			continue;
		}
		else
			_lines[i] << ch;
	}
	_nLines = i + 1;
}

vEditHandler::~vEditHandler() {
	_c = 0;
	_dest = 0;
}

vEditHandler& vEditHandler::operator = ( vEditHandler& it ) {
	_c = it.getC();
	_dest = it.getDest();
	for ( int i=0; i < 40; i++ )
		_lines[i] = it.getLine( i );
	_nLines = it.getNlines();
	return *this;
}

void vEditHandler::update() { // private
	std::string tmp;

	for ( int i=0; i < _nLines; i++ ) {
		tmp << _lines[i];
		if ( i < _nLines - 1 )
			tmp << '\n';
	}

	*_dest = tmp;

	return;
}			

Character* vEditHandler::getC() {
	return _c;
}

std::string* vEditHandler::getDest() {
	return _dest;
}

void vEditHandler::setLine( int i, std::string line ) {
	_lines[i] = line;
	return;
}

std::string vEditHandler::getLine( int i ) {
	return _lines[i];
}

int vEditHandler::getNlines() {
	return _nLines;
}

void vEditHandler::addLine( std::string args ) {
	trim( args, args );
	if ( args.empty() ) {
		_nLines++;
	} else {
		// Append new text to the end of the last line.
		if ( _nLines < 1 ) {
			_nLines = 1;
			_lines[0] = args;
		} else {
			std::string old_line = _lines[_nLines-1];
			trim( old_line, old_line );
			std::string tmp = args;
			rtrim( tmp, tmp );
			ltrim( tmp, tmp );
			std::string new_line = old_line + ' ' + tmp;
			trim( new_line, new_line );

			// Start a new line every 70 characters.
			_lines[_nLines-1].erase();
			int i = 1;
			for ( std::string::iterator it = new_line.begin(); it != new_line.end(); it++, i++ ) {
				_lines[_nLines-1] << (*it);
				if ( i == 69 ) {
					i = 0;
					_nLines++;
				}
			}
		}
	}

	update();

	return;
}

void vEditHandler::insertLine( std::string args ) {
	rtrim( args, args );
	if ( !args.empty() ) {
		std::string line_num;
		std::string line;
		split( args, line_num, line );
		int num = atoi( line_num.c_str() ) - 2;
		if ( num < 1 )
			return;
		int loops = _nLines - num + 1;
		_nLines++;
		for ( int i=0; i < loops; i++ )
			_lines[_nLines-i] = _lines[_nLines-i-1];
		_lines[num+1] = line;
	}

	update();

	return;
}

void vEditHandler::removeLine( std::string args ) {
	rtrim( args, args );
	if ( args.empty() ) {
		if ( _nLines < 1 ) { // Can't erase lines if there are none left to erase!
			update();
			return;
		}
		_lines[--_nLines].erase();
	} else {
		int num = atoi( args.c_str() ) - 1;
		if ( num < 1 )
			return;
		if ( num < 1 || num > _nLines ) {
			update();
			return;
		}
		int loops = _nLines - num;

		_lines[num].erase();

		for ( int i=0; i < loops; i++ )
			_lines[num+i] = _lines[num+i+1];

		_lines[_nLines-1].erase();
		_nLines--;
	}

	update();

	return;
}

void vEditHandler::replaceLine( std::string args ) {
	std::string line_num;
	std::string line;
	split( args, line_num, line );
	int num = atoi( line_num.c_str() );

	if ( num < 1 )
		return;

	if ( line.size() <= 70 && num <= _nLines )
		_lines[ num - 1 ] = line;

	update();

	return;
}

std::string vEditHandler::editWindow() {
	std::string buf;
	std::string tmp;

	buf << "  ----------------------------------------------------------------------------\n\r";
	buf << " |                             {CSymphony Text Editor{x                           |\n\r";
	buf << " | Type 'help' for a list of commands, or 'help <command>' for specific info  |\n\r";
	buf << " |----------------------------------------------------------------------------|\n\r";
	for ( int i=0; i < _nLines; i++ ) {
		buf << " | ";
		if ( i <= 8 )
			buf << " ";
		buf << i+1 << ": " << format( 70, _lines[i], tmp ) << " |\n\r";
	}
	buf << "  ----------------------------------------------------------------------------\n\r";

	return buf;
}

vEditHandler* vEditList::operator [] ( std::string name ) {
	for ( std::list< vEditHandler* >::iterator it = _vList.begin(); it != _vList.end(); it++ )
		if ( (*it)->getC()->getName() == name )
			return (*it);

	return NULL;
}

std::list< vEditHandler* >& vEditList::getList() {
	return _vList;
}

void vEditList::act( Character* c, const string& args ) {
	vEditHandler* vh = 0;
	std::string buf;

	if ( ( vh = Instance()[ c->getName() ] ) == NULL ) {
		if ( c->GetStatus() == CONNECTED )
			_vList.push_back( new vEditHandler( c, &(c->getDesc()) ) );
		else if ( c->GetStatus() == NEDIT )
			_vList.push_back( new vEditHandler( c, &(c->getNote()->getBody()) ) );
		else if ( c->GetStatus() == REDIT )
			_vList.push_back( new vEditHandler( c, &(c->getRoom()->getDesc()) ) );
		else if ( c->GetStatus() == OEDIT )
			_vList.push_back( new vEditHandler( c, &(c->getObject()->getDesc()) ) );
		else if ( c->GetStatus() == MEDIT )
			_vList.push_back( new vEditHandler( c, &(c->getMob()->getDesc()) ) );
		else {
			c->Send( "{RERROR{x\n\r" );
			return;
		}
		buf << "Welcome to Symphony Text Editor!\n\r";
		c->Send( buf );
		return;
	}

	if ( vCommandTable::Instance().Execute( c, args ) == 0 )
		c->Send( vh->editWindow() );
	

	return;
}



#endif // #ifndef VEDIT_HANDLER_CPP
